﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using CarRampCreateAndEdit.Utils;
using YArchitech.Revit.RevitExtension;
using YJKArchMethodLibrary.Utils;

namespace CarRampCreateAndEdit
{
	public class RampCreater
	{
		public RampCreater(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
		}

		public bool CreateFloorBySegementDataList(List<SegmentData> segmentDataList, FloorType floorType)
		{
			if (floorType == null)
			{
				return false;
			}
			List<ThreeLine> thrLines = new List<ThreeLine>();
			if (!this.CalculaterDoubleLine(segmentDataList, ref thrLines))
			{
				return false;
			}
			CurveArray loop = new CurveArray();
			CurveArray loop2 = new CurveArray();
			List<double> widthList = new List<double>();
			List<double> widthList2 = new List<double>();
			List<List<XYZ>> segmentPointList = new List<List<XYZ>>();
			List<List<XYZ>> segmentPointList2 = new List<List<XYZ>>();
			this.CalculaterRampLoop(segmentDataList, thrLines, ref loop, ref segmentPointList, ref widthList, ref loop2, ref segmentPointList2, ref widthList2);
			Level genLevel = this.m_Revit.Application.ActiveUIDocument.ActiveView.GenLevel;
			Transaction transaction = new Transaction(this.m_Revit.Application.ActiveUIDocument.Document);
			transaction.Start("create ramp");
			try
			{
				Floor ramp = this.CreateSingleRamp(floorType, genLevel, loop, true, segmentPointList, widthList);
				Floor ramp2 = this.CreateSingleRamp(floorType, genLevel, loop2, false, segmentPointList2, widthList2);
				List<double> segmentVertRadius = this.GetSegmentVertRadius(segmentDataList);
				ExtensibleStorageManager.WriteRampVertRadius(ramp, segmentVertRadius);
				ExtensibleStorageManager.WriteRampVertRadius(ramp2, segmentVertRadius);
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
				return false;
			}
			return true;
		}

		private void CalculaterRampLoop(List<SegmentData> segmentDataList, List<ThreeLine> thrLines, ref CurveArray curvesLeft, ref List<List<XYZ>> leftSegmentPointList, ref List<double> leftWidthList, ref CurveArray curvesRight, ref List<List<XYZ>> rightSegmentPointList, ref List<double> rightWidthList)
		{
			List<XYZ> list = new List<XYZ>();
			List<XYZ> list2 = new List<XYZ>();
			double startElevation = segmentDataList[0].StartElevation;
			double endElevation = segmentDataList[segmentDataList.Count - 1].EndElevation;
			for (int i = 0; i < thrLines.Count; i++)
			{
				ThreeLine threeLine = thrLines[i];
				if (Geometry.LessThan(startElevation, endElevation))
				{
					leftWidthList.Add(segmentDataList[threeLine.RefObjectIndex].LeftWidth);
					rightWidthList.Add(segmentDataList[threeLine.RefObjectIndex].RightWidth);
				}
				else
				{
					leftWidthList.Insert(0, segmentDataList[threeLine.RefObjectIndex].LeftWidth);
					rightWidthList.Insert(0, segmentDataList[threeLine.RefObjectIndex].RightWidth);
				}
				double num = AssistFunc.mmToFeet(segmentDataList[i].StartElevation);
				double num2 = AssistFunc.mmToFeet(segmentDataList[i].EndElevation);
				XYZ startPoint = threeLine.LeftLine.StartPoint;
				XYZ startPoint2 = threeLine.RightLine.StartPoint;
				XYZ startPoint3 = threeLine.CenterLine.StartPoint;
				XYZ item = new XYZ(startPoint.X, startPoint.Y, num);
				XYZ item2 = new XYZ(startPoint2.X, startPoint2.Y, num);
				XYZ item3 = new XYZ(startPoint3.X, startPoint3.Y, num);
				List<XYZ> list3 = new List<XYZ>();
				list3.Add(item3);
				list3.Add(item);
				List<XYZ> list4 = new List<XYZ>();
				list4.Add(item2);
				list4.Add(item3);
				if (i == 0)
				{
					curvesLeft.Append(YJKLineEx.YJKGetBound(startPoint, startPoint3));
					curvesRight.Append(YJKLineEx.YJKGetBound(startPoint3, startPoint2));
					list.Add(item);
					list2.Add(item2);
				}
				if (i > 0)
				{
					XYZ xyz = leftSegmentPointList[i - 1][2];
					if (!this.IsEqualWidth2dPoint(startPoint, xyz))
					{
						curvesLeft.Insert(YJKLineEx.YJKGetBound(startPoint, new XYZ(xyz.X, xyz.Y, 0.0)), 0);
					}
					XYZ xyz2 = rightSegmentPointList[i - 1][3];
					if (!this.IsEqualWidth2dPoint(startPoint2, xyz2))
					{
						curvesRight.Append(YJKLineEx.YJKGetBound(new XYZ(xyz2.X, xyz2.Y, 0.0), startPoint2));
					}
				}
				if (!threeLine.CenterLine.IsPoint)
				{
					curvesLeft.Append(threeLine.CenterLine.ConvertTo(this.m_Revit.Application.Application));
				}
				if (!threeLine.RightLine.IsPoint)
				{
					curvesRight.Append(threeLine.RightLine.ConvertTo(this.m_Revit.Application.Application));
				}
				if (!threeLine.LeftLine.IsPoint)
				{
					EdgeInfo reverseLeftLine = threeLine.GetReverseLeftLine();
					curvesLeft.Insert(reverseLeftLine.ConvertTo(this.m_Revit.Application.Application), 0);
				}
				if (!threeLine.CenterLine.IsPoint)
				{
					EdgeInfo reverseCenterLine = threeLine.GetReverseCenterLine();
					curvesRight.Insert(reverseCenterLine.ConvertTo(this.m_Revit.Application.Application), 0);
				}
				XYZ endPoint = threeLine.RightLine.EndPoint;
				XYZ endPoint2 = threeLine.LeftLine.EndPoint;
				XYZ endPoint3 = threeLine.CenterLine.EndPoint;
				XYZ item4 = new XYZ(endPoint.X, endPoint.Y, num2);
				XYZ item5 = new XYZ(endPoint2.X, endPoint2.Y, num2);
				XYZ item6 = new XYZ(endPoint3.X, endPoint3.Y, num2);
				list3.Add(item5);
				list3.Add(item6);
				leftSegmentPointList.Add(list3);
				list4.Add(item6);
				list4.Add(item4);
				rightSegmentPointList.Add(list4);
				list.Add(item5);
				list2.Add(item4);
				if (i == thrLines.Count - 1)
				{
					curvesLeft.Append(YJKLineEx.YJKGetBound(endPoint3, endPoint2));
					curvesRight.Append(YJKLineEx.YJKGetBound(endPoint, endPoint3));
				}
			}
		}

		private bool IsEqualWidth2dPoint(XYZ pt1, XYZ pt2)
		{
			XYZ xyz = new XYZ(pt1.X, pt1.Y, 0.0);
			XYZ xyz2 = new XYZ(pt2.X, pt2.Y, 0.0);
			return xyz.IsAlmostEqualTo(xyz2, 1E-09);
		}

		private Floor CreateSingleRamp(FloorType floorType, Level level, CurveArray loop, bool isLeft, List<List<XYZ>> segmentPointList, List<double> widthList)
		{
			Floor floor = this.m_Revit.Application.ActiveUIDocument.Document.Create.NewFloor(loop, floorType, level, false, XYZ.BasisZ);
			if (floor == null)
			{
				return null;
			}
			Common.UpdateModel(this.m_Revit.Application.ActiveUIDocument, false);
			SlabShapeEditor slabShapeEditor = floor.SlabShapeEditor;
			if (slabShapeEditor != null)
			{
				for (int i = 0; i < segmentPointList.Count; i++)
				{
					List<XYZ> list = segmentPointList[i];
					SlabShapeVertex slabShapeVertex = slabShapeEditor.DrawPoint(list[0]);
					SlabShapeVertex slabShapeVertex2 = slabShapeEditor.DrawPoint(list[1]);
					if (i > 0 && slabShapeVertex != null && slabShapeVertex2 != null)
					{
						slabShapeEditor.DrawSplitLine(slabShapeVertex, slabShapeVertex2);
					}
					if (i == segmentPointList.Count - 1)
					{
						slabShapeEditor.DrawPoint(list[2]);
						slabShapeEditor.DrawPoint(list[3]);
					}
					else if (isLeft)
					{
						XYZ xyz = segmentPointList[i + 1][1];
						if (!xyz.IsAlmostEqualTo(list[2]))
						{
							slabShapeEditor.DrawPoint(list[2]);
						}
					}
					else
					{
						XYZ xyz2 = segmentPointList[i + 1][0];
						if (!xyz2.IsAlmostEqualTo(list[3]))
						{
							slabShapeEditor.DrawPoint(list[3]);
						}
					}
				}
			}
			if (!this.CollisionDetection(floor))
			{
				return null;
			}
			ExtensibleStorageManager.WriteRampExtensibleStorage(floor, widthList);
			return floor;
		}

		private bool CollisionDetection(Floor newFloor)
		{
			Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
			ElementIntersectsElementFilter elementIntersectsElementFilter = new ElementIntersectsElementFilter(newFloor, false);
			filteredElementCollector.WherePasses(elementIntersectsElementFilter);
			filteredElementCollector.Excluding(new List<ElementId>
			{
				newFloor.Id
			});
			foreach (Element element in filteredElementCollector)
			{
				if (element.Category.Id.IntegerValue == -2000032)
				{
					MessageBox.Show("插入点已有其他坡道存在！", "盈建科提示");
					return false;
				}
			}
			return true;
		}

		private bool CalculaterDoubleLine(List<SegmentData> segmentDataList, ref List<ThreeLine> thrLines)
		{
			List<double> list = new List<double>();
			List<double> list2 = new List<double>();
			List<Curve> list3 = new List<Curve>();
			foreach (SegmentData segmentData in segmentDataList)
			{
				list.Add(AssistFunc.mmToFeet(segmentData.LeftWidth));
				list2.Add(AssistFunc.mmToFeet(segmentData.RightWidth));
				list3.Add(segmentData.GetCurve(this.m_Revit.Application.Application));
			}
			DoubleLineCliper doubleLineCliper = new DoubleLineCliper(this.m_Revit.Application.Application);
			thrLines = doubleLineCliper.CalculaterDoubleLine(list3, list, list2);
			return thrLines.Count >= 1;
		}

		private List<double> GetSegmentVertRadius(List<SegmentData> lstSegmentData)
		{
			List<double> list = new List<double>();
			foreach (SegmentData segmentData in lstSegmentData)
			{
				list.Add(segmentData.VertArcRadius);
			}
			return list;
		}

		private ExternalCommandData m_Revit;
	}
}
